Skip to content

[InstCombine] Fold fcmp ord/uno (fptrunc X), C to fcmp ord/uno X, C - #185848

Closed
wermos wants to merge 4 commits into
llvm:mainfrom
wermos:fptrunc
Closed

[InstCombine] Fold fcmp ord/uno (fptrunc X), C to fcmp ord/uno X, C#185848
wermos wants to merge 4 commits into
llvm:mainfrom
wermos:fptrunc

Conversation

@wermos

@wermos wermos commented Mar 11, 2026

Copy link
Copy Markdown
Contributor

@wermos
wermos requested a review from nikic as a code owner March 11, 2026 10:07
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Mar 11, 2026
@llvmbot

llvmbot commented Mar 11, 2026

Copy link
Copy Markdown
Member

@llvm/pr-subscribers-llvm-transforms

Author: Tirthankar Mazumder (wermos)

Changes

Fixes #185698.

Alive2 proof: https://alive2.llvm.org/ce/z/682cYT


Full diff: https://github.com/llvm/llvm-project/pull/185848.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+30-22)
  • (modified) llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll (+48-1)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 10caf4ab78a5a..90e9fbb4ab583 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -8359,26 +8359,15 @@ static Instruction *foldFCmpReciprocalAndZero(FCmpInst &I, Instruction *LHSI,
 
 // Transform 'fptrunc(x) cmp C' to 'x cmp ext(C)' if possible.
 // Patterns include:
-//    fptrunc(x) <  C  -->  x <  ext(C)
-//    fptrunc(x) <= C  -->  x <= ext(C)
-//    fptrunc(x) >  C  -->  x >  ext(C)
-//    fptrunc(x) >= C  -->  x >= ext(C)
+//    fptrunc(x) <  C      -->  x <  ext(C)
+//    fptrunc(x) <= C      -->  x <= ext(C)
+//    fptrunc(x) >  C      -->  x >  ext(C)
+//    fptrunc(x) >= C      -->  x >= ext(C)
+//    fptrunc(x) ord/uno C --> x ord/uno C
 // where 'ext(C)' is the extension of 'C' to the type of 'x' with a small bias
 // due to precision loss.
 static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
                                     const Constant &C) {
-  FCmpInst::Predicate Pred = I.getPredicate();
-  bool RoundDown = false;
-
-  if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
-      Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)
-    RoundDown = true;
-  else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT ||
-           Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)
-    RoundDown = false;
-  else
-    return nullptr;
-
   const APFloat *CValue;
   if (!match(&C, m_APFloat(CValue)))
     return nullptr;
@@ -8393,6 +8382,31 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
     return Dest;
   };
 
+  Type *DestType = FPTrunc.getOperand(0)->getType();
+  const fltSemantics &DestFltSema =
+      DestType->getScalarType()->getFltSemantics();
+
+  APFloat ExtCValue = ConvertFltSema(*CValue, DestFltSema);
+
+  FCmpInst::Predicate Pred = I.getPredicate();
+
+  // Fold fcmp ord/uno fptrunc X, C -> fcmp ord/uno X, C
+  if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO) {
+    return new FCmpInst(Pred, FPTrunc.getOperand(0),
+                        ConstantFP::get(DestType, ExtCValue), "", &I);
+  }
+
+  bool RoundDown = false;
+
+  if (Pred == FCmpInst::FCMP_OGE || Pred == FCmpInst::FCMP_UGE ||
+      Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)
+    RoundDown = true;
+  else if (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT ||
+           Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)
+    RoundDown = false;
+  else
+    return nullptr;
+
   auto NextValue = [](const APFloat &Value, bool RoundDown) {
     APFloat NextValue = Value;
     NextValue.next(RoundDown);
@@ -8400,12 +8414,6 @@ static Instruction *foldFCmpFpTrunc(FCmpInst &I, const Instruction &FPTrunc,
   };
 
   APFloat NextCValue = NextValue(*CValue, RoundDown);
-
-  Type *DestType = FPTrunc.getOperand(0)->getType();
-  const fltSemantics &DestFltSema =
-      DestType->getScalarType()->getFltSemantics();
-
-  APFloat ExtCValue = ConvertFltSema(*CValue, DestFltSema);
   APFloat ExtNextCValue = ConvertFltSema(NextCValue, DestFltSema);
 
   // When 'NextCValue' is infinity, use an imaged 'NextCValue' that equals
diff --git a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
index 371f9b6807fe4..7bc5d7fb7a1c6 100644
--- a/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
+++ b/llvm/test/Transforms/InstCombine/fold-fcmp-trunc.ll
@@ -104,7 +104,7 @@ define i1 @fcmp_trunc_with_reassoc(double %0) {
 define i1 @fcmp_trunc_with_fast(double %0) {
 ; CHECK-LABEL: define i1 @fcmp_trunc_with_fast(
 ; CHECK-SAME: double [[TMP0:%.*]]) {
-; CHECK-NEXT:    [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000 
+; CHECK-NEXT:    [[RESULT:%.*]] = fcmp fast oge double [[TMP0]], 0x4058FFFFF0000000
 ; CHECK-NEXT:    ret i1 [[RESULT]]
 ;
   %trunc = fptrunc double %0 to float
@@ -672,3 +672,50 @@ define i1 @fcmp_trunc_mn_ppc_fp128(ppc_fp128 %0) {
   ret i1 %result
 }
 
+define i1 @fptrunc_uno_fcmp(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_uno_fcmp(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp uno float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp uno float %v0, 0.000000e+00
+  ret i1 %v1
+}
+
+define i1 @fptrunc_uno_fcmp_commuted(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_uno_fcmp_commuted(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp uno float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp uno float 7.000000e+00, %v0
+  ret i1 %v1
+}
+
+define i1 @fptrunc_ord_fcmp(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_ord_fcmp(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ord float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp ord float %v0, 0.000000e+00
+  ret i1 %v1
+}
+
+define i1 @fptrunc_ord_fcmp_commuted(double %arg0) {
+; CHECK-LABEL: define i1 @fptrunc_ord_fcmp_commuted(
+; CHECK-SAME: double [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = fptrunc double [[ARG0]] to float
+; CHECK-NEXT:    [[V1:%.*]] = fcmp ord float [[V0]], 0.000000e+00
+; CHECK-NEXT:    ret i1 [[V1]]
+;
+  %v0 = fptrunc double %arg0 to float
+  %v1 = fcmp ord float 7.000000e+00, %v0
+  ret i1 %v1
+}

@wermos wermos changed the title Fold fcmp ord/uno (fptrunc X), C to fcmp ord/uno X, C [InstCombine] Fold fcmp ord/uno (fptrunc X), C to fcmp ord/uno X, C Mar 11, 2026
@github-actions

github-actions Bot commented Mar 11, 2026

Copy link
Copy Markdown

🐧 Linux x64 Test Results

  • 192022 tests passed
  • 4912 tests skipped

✅ The build succeeded and all tests passed.

@github-actions

github-actions Bot commented Mar 11, 2026

Copy link
Copy Markdown

🪟 Windows x64 Test Results

  • 132112 tests passed
  • 2994 tests skipped

✅ The build succeeded and all tests passed.

@wermos

wermos commented Apr 19, 2026

Copy link
Copy Markdown
Contributor Author

Closing this as #185844 was merged.

@wermos wermos closed this Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missed optimization: fold fcmp uno/ord of fptrunc into fcmp of original operand

2 participants